package applet;

import java.applet.Applet;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferStrategy;

import editor.EditorScreen;

/** Displayed in browser. */
public class Game extends Applet implements Runnable {
	/** Auto generated serial version UID. */
	private static final long serialVersionUID = -7120848176473722093L;

	/** The current {@linkplain Thread}. */
	private Thread thread;
	/** */
	private Screen screen;
	/** */
	private Canvas canvas;
	/** */
	private BufferStrategy bufferStrategy;

	/** */
	private Mouse mouse;

	/** Begins a thread to run the game. */
	@Override
	public final void init() {
		thread = new Thread(this);
		thread.start();
	}

	/** Clean up resources. */
	@Override
	public final void destroy() {
		setScreen(null);
		thread = null;
	}

	@Override
	public final void run() {
		// Get rid of annoying offsets
		setLayout(new GridLayout(0, 1, 0, 0));

		// Create the canvas
		canvas = new Canvas();
		canvas.setSize(getSize());
		add(canvas);

		// Create the buffer strategy
		canvas.createBufferStrategy(2);
		bufferStrategy = canvas.getBufferStrategy();

		// Create the cursor
		mouse = new Mouse();
		canvas.addMouseListener(mouse);
		canvas.addMouseMotionListener(mouse);

		// Go to the first screen
		setScreen(new EditorScreen(this));

		// Keep running the screens until null screen is entered
		while (screen != null) {
			screen.run();
		}

		canvas.removeMouseMotionListener(mouse);
		canvas.removeMouseListener(mouse);
		mouse = null;

		bufferStrategy = null;

		canvas = null;
	}

	/**
	 * Calls the draw function of the given screen passing it the
	 * back-buffer's graphics context then updates the display.
	 * 
	 * @param drawMe - the screen to draw.
	 */
	public final void draw(final Screen drawMe) {
		// Draw the screen to the back buffer
		Graphics backGraphics = bufferStrategy.getDrawGraphics();
		drawMe.draw(backGraphics);
		backGraphics.dispose();

		// Draw the back buffer to the display
		try {
			bufferStrategy.show();
		} catch (Exception e) {
			System.err.println("Known bug, not causing any harm but annoying.");
		}
	}

	/**
	 * @param newScreen - the new {@linkplain Screen}.
	 */
	public final void setScreen(final Screen newScreen) {
		screen = newScreen;
	}

	/** @return the current {@linkplain Screen}. */
	public final Screen getScreen() {
		return screen;
	}

	/** @return the {@linkplain Canvas}. */
	public final Canvas getCanvas() {
		return canvas;
	}

	/** @return the {@linkplain Mouse}. */
	public final Mouse getMouse() {
		return mouse;
	}

	@Override
	public final void update(final Graphics g) {
		// Do nothing
	}
}
